package gatperdut.chato.core.combat;

import gatperdut.chato.constants.CSConstantsCombat.AttackResult;
import gatperdut.chato.constants.CSConstantsCombat.BeAttackedResult;
import gatperdut.chato.constants.CSConstantsMovement.Direction;
import gatperdut.chato.core.characters.BaseController;
import gatperdut.chato.core.threads.CombatThread;
import gatperdut.chato.core.threads.FleeThread;

import java.util.List;

public class CombatController {

    private BaseController baseController;

    private CombatThread combatThread = null;

    private FleeThread fleeThread = null;

    public AttackResult attack( BaseController target ) {
        if ( getBaseController().isCrafting() ) {
            return AttackResult.MUST_STOP_CRAFTING_FIRST;
        }

        if ( getBaseController().isPacifist() ) {
            return AttackResult.IS_SET_TO_PACIFIST;
        }

        if ( isInCombat() ) { // --already in combat.
            if ( getCombatThread().getTarget() == null ) {
                return AttackResult.RESUME_COMBAT;
            }
            else if ( getCombatThread().getTarget() == target ) {
                return AttackResult.ATTACKING_SAME_TARGET;
            }
            else {
                return AttackResult.SHIFT_TO_DIFFERENT_TARGET;
            }
        }
        else { // --not in combat.
            return AttackResult.STARTED_ATTACKING;
        }
    }

    public BeAttackedResult beAttacked( BaseController attacker ) {
        if ( getBaseController().isCrafting() ) {
            getBaseController().stopCraftThread();
        }

        if ( isInCombat() ) {
            return BeAttackedResult.ALREADY_FIGHTING;
        }
        else {
            return BeAttackedResult.STARTED_ATTACKING;
        }
    }

    public void handleBecomingNonPacifist( BaseController attacker ) {
        if ( !isAttacking() && !getBaseController().isPacifist() ) {
            getBaseController().getEchoes().txStartFightingBack( attacker );
            setTarget( attacker );
            attacker.getCombatController().addAttacker( getBaseController() );
        }
    }

    public boolean combatCanEnd() {
        return !isAttacking() && !isBeingAttacked();
    }

    public void handleDeadTarget() {
        if ( !isBeingAttacked() ) {
            stopCombatThread();
        }
        else {
            BaseController newTarget = getAttackers().get( 0 );
            getBaseController().getEchoes().txShiftAttention( newTarget );
            setTarget( newTarget );
        }
    }

    public void handleDeadAttacker( BaseController exAttacker ) {
        getAttackers().remove( exAttacker );
    }

    public void handleBecomingPacifist() {
        if ( !isInCombat() ) {
            return;
        }

        if ( isAttacking() ) {
            getTarget().getCombatController().removeAttacker( getBaseController() );
            setTarget( null );
        }

        if ( combatCanEnd() ) {
            stopCombatThread();
        }
    }

    public void startCombatThread( BaseController target ) {
        CombatThread combatThread = new CombatThread( getBaseController(), target );
        setCombatThread( combatThread );
        combatThread.start();
    }

    public void stopCombatThread() {
        if ( isFleeing() ) {
            stopFleeThread();
        }
        getCombatThread().interrupt();
        setCombatThread( null );
    }

    public void startFleeThread( Direction direction ) {
        FleeThread fleeThread = new FleeThread( getBaseController(), direction );
        setFleeThread( fleeThread );
        fleeThread.start();
    }

    public void stopFleeThread() {
        getFleeThread().interrupt();
        setFleeThread( null );
    }

    public void addAttacker( BaseController attacker ) {
        // System.out.println( getBaseController().getCharacter().getName() +
        // " gets a new attacker: " + attacker.getCharacter().getName() );
        getCombatThread().addAttacker( attacker );
    }

    public void removeAttacker( BaseController exAttacker ) {
        // System.out.println( getBaseController().getCharacter().getName() +
        // " loses an attacker: " + exAttacker.getCharacter().getName() );
        getCombatThread().removeAttacker( exAttacker );
    }

    public List<BaseController> getAttackers() {
        return getCombatThread().getAttackers();
    }

    public boolean isFleeing() {
        return getFleeThread() != null;
    }

    public boolean isInCombat() {
        return getCombatThread() != null;
    }

    public boolean isBeingAttacked() {
        return !getCombatThread().getAttackers().isEmpty();
    }

    public boolean isAttacking() {
        return getCombatThread().getTarget() != null;
    }

    public BaseController getTarget() {
        return getCombatThread().getTarget();
    }

    public void setTarget( BaseController target ) {
        getCombatThread().setTarget( target );
    }

    public CombatThread getCombatThread() {
        return combatThread;
    }

    public void setCombatThread( CombatThread combatThread ) {
        this.combatThread = combatThread;
    }

    public FleeThread getFleeThread() {
        return fleeThread;
    }

    public void setFleeThread( FleeThread fleeThread ) {
        this.fleeThread = fleeThread;
    }

    public BaseController getBaseController() {
        return baseController;
    }

    public void setBaseController( BaseController baseController ) {
        this.baseController = baseController;
    }

}
